#ifndef DATA_H
#define DATA_H
#include<QString>
#include<QIcon>
#include<QDebug>
#include <QFileInfo>
#include<QUuid>
namespace module
{
#define format QString("[%1:%2]").arg(module::getFileName(__FILE__),QString::number(__LINE__))
#define LOG() qDebug().noquote()<<format
// 要求函数的定义如果写在 .h 中, 必须加 static 或者 inline (当然两个都加也可以), 避免链接阶段出现 "函数重定义" 的问题.
static inline QString formatTime(int64_t timestamp)
{
    // 先把时间戳, 转换成 QDateTime 对象
    QDateTime dateTime = QDateTime::fromSecsSinceEpoch(timestamp);
    // 把 QDateTime 对象转成 "格式化时间"
    return dateTime.toString("yyyy-MM-dd HH:mm:ss");
}

// 通过这个函数得到 秒级 的时间
static inline int64_t getTime()
{
    return QDateTime::currentSecsSinceEpoch();
}

// 根据 QByteArray, 转成 QIcon
static inline QIcon makeIcon(const QByteArray& byteArray)
{
    QPixmap pixmap;
    pixmap.loadFromData(byteArray);
    QIcon icon(pixmap);
    return icon;
}

static QString getFileName(QString path)
{
    QFileInfo fileInfo(path);
    return fileInfo.fileName();
}
// 读写文件操作.
// 从指定文件中, 读取所有的二进制内容. 得到一个 QByteArray
static inline QByteArray loadFileToByteArray(const QString& path)
{
    QFile file(path);
    bool ok =file.open(QFile::ReadOnly);
    if (!ok)
    {
        LOG() << "文件打开失败!";
        return QByteArray();
    }
    QByteArray content= file.readAll();
    file.close();
    return content;
}

// 把 QByteArray 中的内容, 写入到某个指定文件里
static inline void writeByteArrayToFile(const QString& path, const QByteArray& content)
{
    QFile file(path);
    bool ok =file.open(QFile::WriteOnly);
    if (!ok)
    {
        LOG() << "文件打开失败!";
        return ;
    }
    file.write(content);
    file.flush();
    file.close();
}


///////////////////////////////
/// 用户信息
///////////////////////////////
class User
{
public:
    QString userId=" ";//用户标识
    QString name=" ";//用户名字
    QString description = ""; // 用户签名
    QString phone="";//用户号码
    QIcon  avatar;//用户头像
};

///////////////////////////////////
/// 消息类型
//////////////////////////////////

typedef enum
{
    TEXT_TYPE,          //文本消息
    IMAGE_TYPE, 	// 图片消息
    FILE_TYPE, 		// 文件消息
    SPEECH_TYPE 	// 语音消息
}MessageType;
class  Message
{
public:
    static Message makeMessage(MessageType messageType, const QString& chatSessionId, const User& sender,
                               const QByteArray& content, const QString& extraInfo) {
        if (messageType == TEXT_TYPE) {
            return makeTextMessage(chatSessionId, sender, content);
        } else if (messageType == IMAGE_TYPE) {
            return makeImageMessage(chatSessionId, sender, content);
        } else if (messageType == FILE_TYPE) {
            return makeFileMessage(chatSessionId, sender, content, extraInfo);
        } else if (messageType == SPEECH_TYPE) {
            return makeSpeechMessage(chatSessionId, sender, content);
        } else {
            // 触发了未知的消息类型
            return Message();
        }
    }
public:
    QString messageId="";
    User sender;//消息发送者
    QString sessionId="";//消息说在会话id
    QString time="";//消息发送时间
    QByteArray context;//消息内容
    MessageType messageType;//消息类型
    //这两个属性的设置是为了我们构建一条消息 如果不是文本消息可能会非常大
    //如果我们直接构建消息就会慢
    //如果用fileid我们就可以减少消息构建成本 接着根据文件标识 再去实际请求消息主题部分
    QString fileId = "";				// 文件的身份标识. 当消息类型为 文件, 图片, 语音 的时候, 才有效. 当消息类型为 文本, 则为 ""
    QString fileName = ""; 				// 文件名称. 只是当消息类型为 文件 消息, 才有效. 其他消息均为 ""

private:
    // 通过这个方法生成唯一的 messageId
    static QString makeId() {
        return "M" + QUuid::createUuid().toString().sliced(25, 12);
    }

    static Message makeTextMessage(const QString& chatSessionId, const User& sender, const QByteArray& content) {
        Message message;
        // 此处需要确保, 设置的 messageId 是 "唯一" 的
        message.messageId = makeId();
        message.sessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime()); // 生成一个格式化时间
      //  LOG()<<message.time;
        message.context = content;
        message.messageType = TEXT_TYPE;
        // 对于文本消息来说, 这俩属性不使用, 设为 ""
        message.fileId = "";
        message.fileName = "";
        return message;
    }

    static Message makeImageMessage(const QString& chatSessionId, const User& sender, const QByteArray& content) {
        Message message;
        message.messageId = makeId();
        message.sessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.context= content;
        message.messageType = IMAGE_TYPE;
        // fileId 后续使用的时候再进一步设置
        message.fileId = "";
        // fileName 不使用, 直接设为 ""
        message.fileName = "";
        return message;
    }

    static Message makeFileMessage(const QString& chatSessionId, const User& sender, const QByteArray& content, const QString& fileName) {
        Message message;
        message.messageId = makeId();
        message.sessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.context = content;
        message.messageType = FILE_TYPE;
        // fileId 后续使用的时候进一步设置
        message.fileId = "";
        message.fileName = fileName;
        return message;
    }

    static Message makeSpeechMessage(const QString& chatSessionId, const User& sender, const QByteArray& content) {
        Message message;
        message.messageId = makeId();
        message.sessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.context = content;
        message.messageType = SPEECH_TYPE;
        // fileId 后续使用的时候进一步设置
        message.fileId = "";
        // fileName 不使用, 直接设为 ""
        message.fileName = "";
        return message;
    }
};


//////////////////////////////////////////////////////
/// 会话信息
//////////////////////////////////////////////////////
class Session
{
public:
    QString sessiomId;//会话id
    Message lastMessage;//最后一条消息
    QString sessionName;//单聊显示对方的名字 群聊为群名
    QIcon   sessionAvatar;//显示会话的头像
    QString userId = "";// 对于单聊来说, 表示对方的用户 id, 对于群聊设为 ""

};

}
#endif
